package com.holly.unit.query.util;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.holly.unit.core.enums.QueryRuleEnum;
import com.holly.unit.core.util.DateKitUtil;
import com.holly.unit.db.api.constants.DataBaseConstants;
import com.holly.unit.db.api.context.DbOperatorContext;
import com.holly.unit.query.api.constants.QueryConstants;
import com.holly.unit.query.api.util.QueryUtil;
import com.holly.unit.query.pojo.SysPermissionDataRuleModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.NumberUtils;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 类描述: 查询业务工具类
 *
 * @author fxr
 * @version 1.0.0
 * @date 2022/4/6 15:32
 */
@Slf4j
public class QueryBusiUtil {

    /**
     * 获取请求对应的数据权限规则
     * @return
     */
    public static Map<String, SysPermissionDataRuleModel> getRuleMap() {
        Map<String, SysPermissionDataRuleModel> ruleMap = new HashMap<String, SysPermissionDataRuleModel>();
        List<SysPermissionDataRuleModel> list =DataAutorUtil.loadDataSearchConditon();
        if(list != null&&list.size()>0){
            if(list.get(0)==null){
                return ruleMap;
            }
            for (SysPermissionDataRuleModel rule : list) {
                String column = rule.getRuleColumn();
                if(QueryRuleEnum.SQL_RULES.getValue().equals(rule.getRuleConditions())) {
                    column = QueryConstants.SQL_RULES_COLUMN+rule.getId();
                }
                ruleMap.put(column, rule);
            }
        }
        return ruleMap;
    }

    public static String getSqlRuleValue(String sqlRule){
        try {
            Set<String> varParams = getSqlRuleParams(sqlRule);
            for(String var:varParams){
                String tempValue = converRuleValue(var);
                sqlRule = sqlRule.replace("#{"+var+"}",tempValue);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return sqlRule;
    }

    /**
     * 获取sql中的#{key} 这个key组成的set
     */
    public static Set<String> getSqlRuleParams(String sql) {
        if(StrUtil.isEmpty(sql)){
            return null;
        }
        Set<String> varParams = new HashSet<String>();
        String regex = "\\#\\{\\w+\\}";

        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(sql);
        while(m.find()){
            String var = m.group();
            varParams.add(var.substring(var.indexOf("{")+1,var.indexOf("}")));
        }
        return varParams;
    }

    public static String converRuleValue(String ruleValue) {
        String value = JwtUtil.getSessionData(ruleValue);
        if(StrUtil.isEmpty(value)) {
            value = JwtUtil.getUserSystemData(ruleValue,null);
        }
        return value!= null ? value : ruleValue;
    }


    public static void addRuleToQueryWrapper(SysPermissionDataRuleModel dataRule, String name, Class propertyType, QueryWrapper<?> queryWrapper) {
        QueryRuleEnum rule = QueryRuleEnum.getByValue(dataRule.getRuleConditions());
        if(rule.equals(QueryRuleEnum.IN) && ! propertyType.equals(String.class)) {
            String[] values = dataRule.getRuleValue().split(",");
            Object[] objs = new Object[values.length];
            for (int i = 0; i < values.length; i++) {
                objs[i] = NumberUtils.parseNumber(values[i], propertyType);
            }
            QueryUtil.addEasyQuery(queryWrapper, name, rule, objs);
        }else {
            if (propertyType.equals(String.class)) {
                QueryUtil.addEasyQuery(queryWrapper, name, rule, converRuleValue(dataRule.getRuleValue()));
            }else if (propertyType.equals(Date.class)) {
                String dateStr =converRuleValue(dataRule.getRuleValue());
                if(dateStr.length()==10){
                    QueryUtil.addEasyQuery(queryWrapper, name, rule, DateKitUtil.str2Date(dateStr,DateKitUtil.date_sdf.get()));
                }else{
                    QueryUtil.addEasyQuery(queryWrapper, name, rule, DateKitUtil.str2Date(dateStr,DateKitUtil.datetimeFormat.get()));
                }
            }else {
                QueryUtil.addEasyQuery(queryWrapper, name, rule, NumberUtils.parseNumber(dataRule.getRuleValue(), propertyType));
            }
        }
    }

    public static String getSingleSqlByRule(QueryRuleEnum rule,String field,Object value,boolean isString) {
        String res = "";
        switch (rule) {
            case GT:
                res =field+rule.getValue()+getFieldConditionValue(value, isString);
                break;
            case GE:
                res = field+rule.getValue()+getFieldConditionValue(value, isString);
                break;
            case LT:
                res = field+rule.getValue()+getFieldConditionValue(value, isString);
                break;
            case LE:
                res = field+rule.getValue()+getFieldConditionValue(value, isString);
                break;
            case EQ:
                res = field+rule.getValue()+getFieldConditionValue(value, isString);
                break;
            case NE:
                res = field+" <> "+getFieldConditionValue(value, isString);
                break;
            case IN:
                res = field + " in "+getInConditionValue(value, isString);
                break;
            case LIKE:
                res = field + " like "+getLikeConditionValue(value);
                break;
            case LEFT_LIKE:
                res = field + " like "+getLikeConditionValue(value);
                break;
            case RIGHT_LIKE:
                res = field + " like "+getLikeConditionValue(value);
                break;
            default:
                res = field+" = "+getFieldConditionValue(value, isString);
                break;
        }
        return res;
    }

    private static String getFieldConditionValue(Object value,boolean isString) {
        String str = value.toString().trim();
        if(str.startsWith("!")) {
            str = str.substring(1);
        }else if(str.startsWith(">=")) {
            str = str.substring(2);
        }else if(str.startsWith("<=")) {
            str = str.substring(2);
        }else if(str.startsWith(">")) {
            str = str.substring(1);
        }else if(str.startsWith("<")) {
            str = str.substring(1);
        }
        if(isString) {
            if(DataBaseConstants.DB_TYPE_SQLSERVER.equals(getDbType())){
                return " N'"+str+"' ";
            }else{
                return " '"+str+"' ";
            }
        }else {
            return value.toString();
        }
    }

    private static String getInConditionValue(Object value,boolean isString) {
        if(isString) {
            String temp[] = value.toString().split(",");
            String res="";
            for (String string : temp) {
                if(DataBaseConstants.DB_TYPE_SQLSERVER.equals(getDbType())){
                    res+=",N'"+string+"'";
                }else{
                    res+=",'"+string+"'";
                }
            }
            return "("+res.substring(1)+")";
        }else {
            return "("+value.toString()+")";
        }
    }

    private static String getLikeConditionValue(Object value) {
        String str = value.toString().trim();
        if(str.startsWith("*") && str.endsWith("*")) {
            if(DataBaseConstants.DB_TYPE_SQLSERVER.equals(getDbType())){
                return "N'%"+str.substring(1,str.length()-1)+"%'";
            }else{
                return "'%"+str.substring(1,str.length()-1)+"%'";
            }
        }else if(str.startsWith("*")) {
            if(DataBaseConstants.DB_TYPE_SQLSERVER.equals(getDbType())){
                return "N'%"+str.substring(1)+"'";
            }else{
                return "'%"+str.substring(1)+"'";
            }
        }else if(str.endsWith("*")) {
            if(DataBaseConstants.DB_TYPE_SQLSERVER.equals(getDbType())){
                return "N'"+str.substring(0,str.length()-1)+"%'";
            }else{
                return "'"+str.substring(0,str.length()-1)+"%'";
            }
        }else {
            if(str.indexOf("%")>=0) {
                if(DataBaseConstants.DB_TYPE_SQLSERVER.equals(getDbType())){
                    if(str.startsWith("'") && str.endsWith("'")){
                        return "N"+str;
                    }else{
                        return "N"+"'"+str+"'";
                    }
                }else{
                    if(str.startsWith("'") && str.endsWith("'")){
                        return str;
                    }else{
                        return "'"+str+"'";
                    }
                }
            }else {
                if(DataBaseConstants.DB_TYPE_SQLSERVER.equals(getDbType())){
                    return "N'%"+str+"%'";
                }else{
                    return "'%"+str+"%'";
                }
            }
        }
    }

    /***
     * 获取当前连接数据库类型
     * @return
     */
    private static String getDbType() {
        return DbOperatorContext.me().getDatabaseType();
    }


}
